﻿using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AyuBookmark.Common.Interfaces;
using Microsoft.Extensions.Logging;

namespace AyuBookmark.Service.Pipes
{
    /// <summary>
    /// 命名管道服务器实现
    /// </summary>
    public class PipeServer : IDisposable
    {
        private readonly string _pipeName;
        private readonly IMessageProcessor _messageProcessor;
        private readonly ILogger<PipeServer> _logger;
        private NamedPipeServerStream _serverStream;
        private CancellationTokenSource _cts;
        private bool _disposed;

        /// <summary>
        /// 初始化管道服务器
        /// </summary>
        /// <param name="pipeName">管道名称</param>
        /// <param name="messageProcessor">消息处理器</param>
        /// <param name="logger">日志记录器</param>
        public PipeServer(
            string pipeName,
            IMessageProcessor messageProcessor,
            ILogger<PipeServer> logger)
        {
            _pipeName = pipeName ?? throw new ArgumentNullException(nameof(pipeName));
            _messageProcessor = messageProcessor ?? throw new ArgumentNullException(nameof(messageProcessor));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 启动管道服务器
        /// </summary>
        public void Start()
        {
            if (_serverStream != null)
            {
                throw new InvalidOperationException("Server is already running");
            }

            _cts = new CancellationTokenSource();
            Task.Run(() => RunServerAsync(_cts.Token));
            _logger.LogInformation("Pipe server started with name: {PipeName}", _pipeName);
        }

        /// <summary>
        /// 停止管道服务器
        /// </summary>
        public void Stop()
        {
            _cts?.Cancel();
            _serverStream?.Dispose();
            _serverStream = null;
            _logger.LogInformation("Pipe server stopped");
        }

        /// <summary>
        /// 运行服务器主循环
        /// </summary>
        private async Task RunServerAsync(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    _serverStream = new NamedPipeServerStream(
                        _pipeName,
                        PipeDirection.InOut,
                        NamedPipeServerStream.MaxAllowedServerInstances,
                        PipeTransmissionMode.Message,
                        PipeOptions.Asynchronous);

                    _logger.LogDebug("Waiting for client connection...");
                    await _serverStream.WaitForConnectionAsync(cancellationToken);

                    if (_serverStream.IsConnected)
                    {
                        _logger.LogInformation("Client connected");
                        await HandleClientAsync(_serverStream, cancellationToken);
                    }
                }
                catch (OperationCanceledException)
                {
                    _logger.LogInformation("Server shutdown requested");
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error in pipe server");
                }
                finally
                {
                    Disconnect();
                }
            }
        }

        /// <summary>
        /// 处理客户端连接
        /// </summary>
        private async Task HandleClientAsync(NamedPipeServerStream stream, CancellationToken cancellationToken)
        {
            using (var reader = new StreamReader(stream, Encoding.UTF8, false, 1024, leaveOpen: true))
            using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, leaveOpen: true))
            {
                while (!cancellationToken.IsCancellationRequested && stream.IsConnected)
                {
                    try
                    {
                        var message = await reader.ReadLineAsync();
                        if (string.IsNullOrEmpty(message))
                        {
                            _logger.LogDebug("Received empty message, client may have disconnected");
                            break;
                        }

                        _logger.LogDebug("Received message: {Message}", message);
                        var response = await _messageProcessor.ProcessAsync(message, cancellationToken);

                        await writer.WriteLineAsync(response);
                        await writer.FlushAsync();
                        _logger.LogDebug("Sent response: {Response}", response);
                    }
                    catch (IOException ex)
                    {
                        _logger.LogWarning(ex, "Client disconnected unexpectedly");
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// 断开当前客户端连接
        /// </summary>
        private void Disconnect()
        {
            try
            {
                if (_serverStream != null)
                {
                    _logger.LogDebug("Disconnecting client");
                    _serverStream.Disconnect();
                    _serverStream.Dispose();
                    _serverStream = null;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error disconnecting pipe");
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    Stop();
                    _cts?.Dispose();
                }
                _disposed = true;
            }
        }

        ~PipeServer()
        {
            Dispose(false);
        }
    }
}